package com.untour.im.server.service.impl;

import com.untour.im.codec.protocol.packet.request.header.RequestPacketHeader;
import com.untour.im.common.enums.DeviceMultiLoginEnum;
import com.untour.im.common.enums.ParamErrorCodeEnum;
import com.untour.im.exception.BusinessException;
import com.untour.im.server.config.ImConfigProperties;
import com.untour.im.server.dto.UserChannelInfo;
import com.untour.im.server.service.DeviceMultiLoginService;
import com.untour.im.server.service.UserChannelService;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class UserChannelServiceImpl implements UserChannelService {
    private static final Map<String, List<UserChannelInfo>> userIdChannelsMap = new ConcurrentHashMap<>();
    private static final Map<String, String> channelIdUserIdMap = new ConcurrentHashMap<>();
    private final ImConfigProperties imConfigProperties;

    private static final Map<Integer, DeviceMultiLoginService> deviceMultiLoginServiceMap = new HashMap<>();

    public UserChannelServiceImpl(ImConfigProperties imConfigProperties,
                                  List<DeviceMultiLoginService> deviceMultiLoginServiceList) {
        this.imConfigProperties = imConfigProperties;
        deviceMultiLoginServiceList.forEach(loginService ->
                deviceMultiLoginServiceMap.put(loginService.deviceMultiLogin().getValue(),loginService));
    }

    @Override
    public void saveUserChannel(ChannelHandlerContext ctx, String userId, RequestPacketHeader header) {
        //根据配置的登录策略来判断是否可以登录，并保存channel信息
        DeviceMultiLoginEnum loginEnum = this.getDeviceMultiLoginEnum();
        deviceMultiLoginServiceMap.get(loginEnum.getValue())
                .saveUserChannel(ctx,userId,header, userIdChannelsMap, channelIdUserIdMap);
    }

    /**
     * 获取登录模式
     * @return
     */
    private DeviceMultiLoginEnum getDeviceMultiLoginEnum() {
        DeviceMultiLoginEnum loginEnum = DeviceMultiLoginEnum.getByValue(imConfigProperties.getLoginModel().getValue());
        if(null == loginEnum){
            throw new BusinessException(ParamErrorCodeEnum.PARAM_ERROR);
        }
        return loginEnum;
    }

    @Override
    public void removeChannelAndUserCache(ChannelHandlerContext ctx) {
        DeviceMultiLoginEnum loginEnum = this.getDeviceMultiLoginEnum();
        deviceMultiLoginServiceMap.get(loginEnum.getValue())
                .removeChannelAndUserCache(ctx, userIdChannelsMap, channelIdUserIdMap);
    }
}
